package avicit.bdp.dcs.semistructure.service;

import avicit.bdp.common.dto.BdpFileStatus;
import avicit.bdp.common.service.service.FileCommonService;
import avicit.bdp.common.service.service.FileOperateCommonService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.common.utils.DateUtils;
import avicit.bdp.common.utils.enums.FileType;
import avicit.bdp.common.utils.enums.UploadStatus;
import avicit.bdp.common.utils.file.FileChunkUtils;
import avicit.bdp.common.utils.redis.RedisCacheHelper;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.core.file.util.FileUtils;
import avicit.bdp.dcs.semistructure.dto.*;
import avicit.bdp.dcs.tools.enums.FileStatusEnum;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.exception.BusinessException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.fs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @金航数码科技有限责任公司
 * @作者：developer
 * @邮箱：developer@avic-digital.com
 * @创建时间： 2020-09-24 14:55
 * @类说明：文件管理实现类
 * @修改记录：
 */
@Service
@Transactional
public class DcsFileService {

  private static final Logger logger = LoggerFactory.getLogger(DcsFileService.class);
  private static final int ZERO = 0;
  private static final int ONE = 1;
  private static final int FILE_SIZE = 1024;

  // 创建线程池
  private final ThreadPoolExecutor delFileThreadPool =
      new ThreadPoolExecutor(
          5,
          10,
          1000L,
          TimeUnit.MILLISECONDS,
          new LinkedBlockingQueue<>(10240),
          r -> new Thread(r, "delFileThreadPool" + r.hashCode()),
          new ThreadPoolExecutor.CallerRunsPolicy());

  @Autowired private CatalogTemplateService catalogTemplateService;

  @Autowired private TemplateService templateService;

  @Autowired private JobFileService jobFileService;

  @Autowired private AsyncFileService asyncFileService;

  @Autowired private FileOperateCommonService fileOperateCommonService;

  @Autowired private FileCommonService fileCommonService;

  @Autowired private RedisCacheHelper redisCacheHelper;
  @Autowired private FileChunkUtils fileChunkUtils;

  /**
   * 记录文件上传信息至数据库
   *
   * @param catalogTemplateDTO 目录模板关联实体
   */
  public void saveUploadInfo(CatalogTemplateDTO catalogTemplateDTO) {

    logger.info("saveUploadInfo: {}", catalogTemplateDTO.toString());
    CheckParaUtils.checkStringValidity(catalogTemplateDTO.getCatalogPath(), logger, "上传文件路径不能为空！");
    CheckParaUtils.checkStringValidity(catalogTemplateDTO.getFilePath(), logger, "上传文件名称不能为空！");

    // 保存文件，目录，模板关系至数据库
    String[] split = catalogTemplateDTO.getFilePath().split(Constants.COMMA);
    for (String filePath : split) {
      // 先查询数据库数据是否存在
      CatalogTemplateDTO catalogTemplateDTOQuery =
          CatalogTemplateDTO.builder()
              .filePath(catalogTemplateDTO.getCatalogPath() + File.separator + filePath)
              .build();
      List<CatalogTemplateDTO> catalogTemplateDTOList =
          catalogTemplateService.selectList(catalogTemplateDTOQuery);
      if (CollectionUtils.isNotEmpty(catalogTemplateDTOList)) {
        logger.error(
            String.format(
                "上传文件已经关联模板：%s", catalogTemplateDTO.getCatalogPath() + File.separator + filePath));
        continue;
      }

      // 根据模板对文件进行校验
      logger.info(
          "根据模板对文件进行校验:{},{}",
          catalogTemplateDTO.getTemplateId(),
          catalogTemplateDTO.getCatalogPath() + File.separator + filePath);
      checkUploadFile(
          catalogTemplateDTO.getCatalogPath() + File.separator + filePath,
          catalogTemplateDTO.getTemplateId());

      catalogTemplateDTO.setId(ComUtil.getId());
      catalogTemplateDTO.setFilePath(
          catalogTemplateDTO.getCatalogPath() + File.separator + filePath);

      logger.info("记录上传信息：{}", catalogTemplateDTO);

      // 记录日志
      BdpLogUtil.log4Insert(catalogTemplateDTO);

      catalogTemplateService.insert(catalogTemplateDTO);
    }
  }

  /**
   * 校验模板
   * @param filePath
   * @param templateId
   */
  private void checkUploadFile(String filePath, String templateId) {
    // 根据模板id获取模板信息
    logger.info("校验模板id为：{}", templateId);
    TemplateDTO templateDTO = templateService.selectByPrimaryKey(templateId);
    CheckParaUtils.checkObjectValidity(templateDTO, logger, "没有找见指定的模板");

    BdpFileStatus fileStatus;
    try {
      fileStatus = fileOperateCommonService.getFileStatus(filePath);
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
      throw new BusinessException(String.format("获取文件状态信息失败：%s", filePath));
    }

    // 校验文件名称长度
    checkFileNameLength(FileUtils.getNameByPath(filePath), templateDTO);

    // 校验上传文件大小
    checkFileSize(fileStatus.getLength(), templateDTO);

    // 校验上传文件类型
    checkFileType(FileUtils.getNameByPath(filePath), templateDTO);
  }

  /**
   * 上传模板
   * @param file
   * @param path
   */
  public void uploadTemplate(MultipartFile file, String path) {

    path = path + Constants.SINGLE_SLASH + file.getOriginalFilename();
    try {
      fileOperateCommonService.upload(file.getInputStream(), path);
    } catch (IOException e) {
      logger.error(e.getMessage(), e);
      throw new BusinessException(e.getMessage());
    }
  }

  /**
   * 效验文件类型
   * @param fileName
   * @param templateDTO
   */
  private void checkFileType(String fileName, TemplateDTO templateDTO) {
    String fileType = fileName.split("\\.")[ONE];
    Integer templateDTOFileType = templateDTO.getFileType();
    FileType[] values = FileType.values();
    for (FileType fileTypeEumn : values) {
      if (fileTypeEumn.getCode() == templateDTOFileType) {
        if (!fileType.equalsIgnoreCase(fileTypeEumn.getSuffix())) {
          throw new BusinessException(
              String.format("上传文件类型不符合要求，文件类型为：%s，限制文件类型为：%s", fileType, fileTypeEumn.getSuffix()));
        }
      }
    }
  }

  /**
   * 效验文件大小
   * @param fileSize
   * @param templateDTO
   */
  private void checkFileSize(long fileSize, TemplateDTO templateDTO) {
    Integer fileSizeLimit = templateDTO.getFileSizeLimit();
    long fileSizeResult = fileSize / FILE_SIZE / FILE_SIZE;
    if (fileSizeResult > fileSizeLimit) {
      throw new BusinessException(
          String.format("上传文件大小超出限制，文件大小为：%dM，限制大小为：%dM", fileSizeResult, fileSizeLimit));
    }
  }

  /**
   * 效验文件名长度
   * @param originalFilename
   * @param templateDTO
   */
  private void checkFileNameLength(String originalFilename, TemplateDTO templateDTO) {
    Integer lengthLimit = templateDTO.getLengthLimit();
    String fileName = originalFilename.split("\\.")[ZERO];
    if (fileName.length() > lengthLimit) {
      throw new BusinessException(
          String.format("上传文件名称过长，文件名称为：%s，长度限制为：%s", fileName, lengthLimit));
    }
  }

  public void batchUpload(String srcPath, String path, String type) throws IOException {
    File file = new File(srcPath);
    File[] files = file.listFiles();
    for (File tempFile : files) {
      if (tempFile.isDirectory()) {
        batchUpload(tempFile.getAbsolutePath(), path, type);
      } else {
        if (tempFile.getName().contains(type)) {
          fileOperateCommonService.copyLocalToServer(
              tempFile.getAbsolutePath(), path, false, false);
        }
      }
    }
  }

  public List<FileDto> getFileList(
      String fileName, String catalogPath, Long startTime, Long endTime) throws Exception {
    if (StringUtils.isEmpty(catalogPath)) {
      catalogPath = fileOperateCommonService.getDCSStoragePath();
    }

    // 查询目录关联的所有模板；做到只和数据库交互一次，提高程序性能
    List<TemplateDTO> templateDTOS =
        templateService.getTemplateDTOAndFilePathByCatalogPath(catalogPath);
    Map<String, String> filePathTemplateMap =
        templateDTOS.stream()
            .collect(Collectors.toMap(TemplateDTO::getFilePath, TemplateDTO::getTemplateName));

    List<FileDto> list = new ArrayList<>();
    List<BdpFileStatus> listStatus = fileOperateCommonService.listFileStatus(catalogPath);
    for (BdpFileStatus fileStatus : listStatus) {
      if (fileStatus.isFile()) {
        getFilterFileList(fileName, startTime, endTime, list, fileStatus, filePathTemplateMap);
      }
    }

    // 根据文件修改时间进行排序
    return list.stream()
        .sorted(Comparator.comparing(FileDto::getUpdateDate).reversed())
        .collect(Collectors.toList());
  }

  private void getFilterFileList(
      String fileName,
      Long startTime,
      Long endTime,
      List<FileDto> list,
      BdpFileStatus fileStatus,
      Map<String, String> filePathTemplateMap) {
    // fileName, startTime, endTime用于文件的模糊查找，单纯获取文件并不需要这三个参数。
    if (StringUtils.isNotEmpty(fileName)) {
      String hdfsFileName = fileStatus.getFileName();
      if (!hdfsFileName.toLowerCase().contains(fileName.toLowerCase())) {
        return;
      }
    }
    if (startTime != null) {
      if (fileStatus.getModificationTime() < startTime) {
        return;
      }
    }
    if (endTime != null) {
      if (fileStatus.getModificationTime() > endTime) {
        return;
      }
    }

    FileDto fileDto =
        FileDto.builder()
            .filePath(fileStatus.getFilePath())
            .fileName(fileStatus.getFileName())
            .fileSize(FileUtils.readableFileSize(fileStatus.getLength(), true))
            .updateDate(DateUtils.getDateByString(new Date(fileStatus.getModificationTime())))
            .templateName(filePathTemplateMap.get(fileStatus.getFilePath()))
            .build();

    // 查询文件上传进度
    final String uploadFileMergeChunk =
        String.format(
            Constants.UPLOADER_FILE_MERGE_CHUNK + "_%s_%s",
            fileStatus.getParentFilePath(),
            fileStatus.getFilePath());

    String chunk = redisCacheHelper.hget(uploadFileMergeChunk, "chunk");
    String chunks = redisCacheHelper.hget(uploadFileMergeChunk, "chunks");
    String uploadStatus = redisCacheHelper.hget(uploadFileMergeChunk, "status");

    if (StringUtils.isEmpty(chunk)
        || StringUtils.isEmpty(chunks)
        || StringUtils.isEmpty(uploadStatus)) {
      fileDto.setProgress(null);
      fileDto.setUploadStatus(null);
    } else {
      // 获取上传进度百分比,上传文件状态
      String percent = getPercent(Long.valueOf(chunk), Long.valueOf(chunks));
      fileDto.setProgress(percent);
      fileDto.setUploadStatus(UploadStatus.valueOf(Integer.parseInt(uploadStatus)).getDesc());
    }

    list.add(fileDto);
  }

  /**
   * 删除文件
   * @param filePaths
   * @return
   * @throws Exception
   */
  public Boolean deleteFileByPaths(String filePaths) throws Exception {
    if (StringUtils.isEmpty(filePaths)) {
      logger.error("删除文件失败,filePaths={}", filePaths);
      throw new BusinessException("没有传入待删除的文件路径");
    }

    // 递归方式删除文件或目录
    String[] filePathsArr = filePaths.split(Constants.COMMA);
    for (String filePath : filePathsArr) {
      // 查询文件上传进度
      final String uploadFileMergeChunk =
          String.format(
              Constants.UPLOADER_FILE_MERGE_CHUNK + "_%s_%s",
              new File(filePath).getParent(),
              new File(filePath).getName());
      logger.info(
          "删除文件路径为：{}， 名称为：{}", new File(filePath).getParent(), new File(filePath).getName());

      String chunk = redisCacheHelper.hget(uploadFileMergeChunk, "chunk");
      String chunks = redisCacheHelper.hget(uploadFileMergeChunk, "chunks");
      String uploadStatus = redisCacheHelper.hget(uploadFileMergeChunk, "status");
      logger.warn("删除文件-文件上传状态为:{}", uploadStatus);

      if (StringUtils.isNotEmpty(chunk)
          || StringUtils.isNotEmpty(chunks)
          || StringUtils.isNotEmpty(uploadStatus)) {
        if (StringUtils.isNotEmpty(uploadStatus)) {
          UploadStatus status = UploadStatus.valueOf(Integer.valueOf(uploadStatus));
          if (status == UploadStatus.UPLOADING || status == UploadStatus.PAUSE) {
            throw new BusinessException("正在上传的或者暂停上传的文件不能删除！");
          }
        } else {
          throw new BusinessException("正在上传的或者暂停上传的文件不能删除！");
        }
      }

      //            if (StringUtils.isNotEmpty(chunk) || StringUtils.isNotEmpty(chunks) ||
      // StringUtils.isNotEmpty(uploadStatus)) {
      //                throw new BusinessException("正在上传的或者暂停上传的文件不能删除！");
      //            }

      if (fileOperateCommonService.exists(filePath)) {
        if (!fileOperateCommonService.delete(filePath, false)) {
          logger.error("递归方式删除文件%s失败：{}", filePath);
          throw new BusinessException(String.format("递归方式删除文件%s失败", filePath));
        }
      }

      // 删除redis中缓存的文件断点信息
      fileCommonService.deleteRedisCacheFileInfo(filePath);

      // 删除文件关联的模板，目录信息
      CatalogTemplateDTO catalogTemplateDTO =
          CatalogTemplateDTO.builder().filePath(filePath).build();

      // 记录日志
      BdpLogUtil.log4Delete(catalogTemplateDTO);
      catalogTemplateService.delete(catalogTemplateDTO);

      // 先清除文件对应的已经同步到数据库中的数据：例如已经同步到iotdb中的数据，如果清除失败，则报错
      // 半结构化删除文件异步删除文件关联的数据
      AsyncFileDTO asyncFileDTO = new AsyncFileDTO();
      asyncFileDTO.setId(ComUtil.getId());
      asyncFileDTO.setFilePath(filePath);
      asyncFileDTO.setStatus(FileStatusEnum.UNDELETE.getCode());
      asyncFileService.insert(asyncFileDTO);

      DelFileTask delFileTask = new DelFileTask(filePath);
      delFileThreadPool.execute(delFileTask);
    }
    return true;
  }

  // 删除hive表对应的hdfs文件
  public Boolean deleteFileByPath(String filePath) throws Exception {
    if (StringUtils.isEmpty(filePath)) {
      logger.error("删除文件失败,filePath={}", filePath);
      throw new BusinessException("没有传入待删除的文件路径");
    }

    // 递归方式删除文件或目录
    if (fileOperateCommonService.exists(filePath)) {
      if (!fileOperateCommonService.delete(filePath, false)) {
        logger.error("递归方式删除文件:{}失败", filePath.toString());
        throw new BusinessException(String.format("递归方式删除文件:%s失败", filePath));
      }
    }
    return true;
  }

  public CatalogDto getCatalogTree(String parentCatalogPath) throws Exception {
    if (StringUtils.isEmpty(parentCatalogPath)) {
      parentCatalogPath = fileOperateCommonService.getDCSStoragePath();
      if (!fileOperateCommonService.exists(parentCatalogPath)) {
        fileOperateCommonService.mkdir(parentCatalogPath);
      }
    }

    Path path = new Path(parentCatalogPath);
    CatalogDto catalogDto =
        CatalogDto.builder()
            .catalogName(path.getName())
            .catalogPath(parentCatalogPath)
            .parentCatalogPath(
                Constants.SINGLE_SLASH.equals(parentCatalogPath) ? "" : path.getParent().toString())
            .build();
    return getCatalogTree(parentCatalogPath, catalogDto);
  }

  /**
   * 递归遍历打印HDFS的目录树
   *
   * @param path 存储路径
   * @throws IOException e
   */
  public CatalogDto getCatalogTree(String path, CatalogDto catalogDto) throws Exception {
    List<CatalogDto> list = new ArrayList<>();

    List<BdpFileStatus> listStatus = fileOperateCommonService.listFileStatus(path);
    for (BdpFileStatus fileStatus : listStatus) {
      if (fileStatus.isDirectory()) {
        CatalogDto childrenCatalogDTO =
            CatalogDto.builder()
                .parentCatalogPath(path)
                .catalogPath(fileStatus.getFilePath())
                .catalogName(fileStatus.getFileName())
                .lastestCatalog(true)
                .build();
        List<BdpFileStatus> fileStatuses =
            fileOperateCommonService.listFileStatus(fileStatus.getFilePath());
        for (BdpFileStatus file : fileStatuses) {
          if (file.isDirectory()) {
            childrenCatalogDTO.setLastestCatalog(false);
          }
        }

        // 根目录配置两层，再向下获取两层深度目录
        if (FileUtils.getDepthByPath(fileStatus.getFilePath()) < 4) {
          getCatalogTree(fileStatus.getFilePath(), childrenCatalogDTO);
        }
        list.add(childrenCatalogDTO);
      }
    }
    catalogDto.setChildren(list);
    return catalogDto;
  }

  public Boolean deleteCatalogByPath(String catalogPath) throws Exception {
    if (StringUtils.isEmpty(catalogPath)) {
      throw new BusinessException("没有传入待删除的目录路径");
    }

    try {
      fileOperateCommonService.delete(catalogPath, false);
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
      throw new BusinessException("删除文件失败，提示：非空目录不能删除！");
    }

    return true;
  }

  public Boolean saveCatalog(CatalogDto catalogDto) throws Exception {
    String parentCatalogPath = catalogDto.getParentCatalogPath();
    if (StringUtils.isEmpty(parentCatalogPath)) {
      parentCatalogPath = fileOperateCommonService.getDCSStoragePath();
    }
    String catalogName = catalogDto.getCatalogName();
    if (StringUtils.isEmpty(catalogName)) {
      throw new BusinessException("创建的文件目录名称不能为空！");
    }

    logger.info("创建目录名称为：{}", parentCatalogPath + Constants.SINGLE_SLASH + catalogName);
    return fileOperateCommonService.mkdir(parentCatalogPath + Constants.SINGLE_SLASH + catalogName);
  }

  public Boolean cancelFileTemplate(CatalogTemplateDTO catalogTemplateDTO) throws Exception {
    // 参数校验
    String filePath = catalogTemplateDTO.getFilePath();
    if (StringUtils.isEmpty(filePath)) {
      throw new BusinessException("filePath不能为空！");
    }

    String[] filePaths = filePath.split(Constants.COMMA);
    for (String filePathstr : filePaths) {
      // 判断目录是否关联模板，未关联模板不能取消
      CatalogTemplateDTO catalogTemplateDTOQuery = new CatalogTemplateDTO();
      catalogTemplateDTOQuery.setFilePath(filePathstr);
      List<CatalogTemplateDTO> catalogTemplate =
          catalogTemplateService.selectList(catalogTemplateDTOQuery);
      if (CollectionUtils.isEmpty(catalogTemplate)) {
        throw new BusinessException(String.format("目录未关联模板，不能取消关联：%s", filePathstr));
      }

      // 记录日志
      BdpLogUtil.log4Delete(catalogTemplateDTOQuery);

      // 删除模板文件关联数据
      catalogTemplateService.delete(catalogTemplateDTOQuery);
    }

    return true;
  }

  public Boolean saveCatalogTemplate(CatalogTemplateDTO catalogTemplateDTO) throws Exception {
    // 参数校验
    String catalogPath = catalogTemplateDTO.getCatalogPath();
    if (StringUtils.isEmpty(catalogPath)) {
      throw new BusinessException("catalogPath不能为空！");
    }
    if (StringUtils.isEmpty(catalogTemplateDTO.getTemplateId())) {
      throw new BusinessException("templateId不能为空！");
    }

    // 判断目录是否最底层目录
    boolean isLastDir = fileOperateCommonService.isLastDir(catalogPath);
    if (!isLastDir) {
      throw new BusinessException(String.format("目录不是最底层目录，不能关联模板：%s", catalogPath));
    }

    // 判断目录是否关联模板，关联以后不支持修改模板
    CatalogTemplateDTO catalogTemplateDTOQuery = new CatalogTemplateDTO();
    catalogTemplateDTOQuery.setCatalogPath(catalogPath);
    List<CatalogTemplateDTO> catalogTemplateList =
        catalogTemplateService.selectList(catalogTemplateDTOQuery);
    if (CollectionUtils.isNotEmpty(catalogTemplateList)) {
      throw new BusinessException(String.format("目录已关联模板，不能重复关联：%s", catalogPath));
    }

    // 判断目录是否为空目录，如果不是空目录不能关联模板
    List<BdpFileStatus> fileStatuses = fileOperateCommonService.listFileStatus(catalogPath);
    if (CollectionUtils.isNotEmpty(fileStatuses)) {
      throw new BusinessException(String.format("只有空目录才能关联模板：%s", catalogPath));
    }

    // 新增目录关联模板
    catalogTemplateDTO.setId(ComUtil.getId());

    // 记录日志
    BdpLogUtil.log4Insert(catalogTemplateDTO);

    catalogTemplateService.insert(catalogTemplateDTO);
    return true;
  }

  public FileDto getFileAttribute(String filePath) throws Exception {
    FileDto fileDto = new FileDto();
    Path fpPath = new Path(filePath);
    BdpFileStatus fileStatus = fileOperateCommonService.getFileStatus(filePath);
    if (fileStatus != null) {
      fileDto.setFileName(fpPath.getName());
      fileDto.setFilePath(fpPath.toString());
      fileDto.setFileSize(FileUtils.readableFileSize(fileStatus.getLength(), true));
      fileDto.setUpdateDate(DateUtils.getDateByString(new Date(fileStatus.getModificationTime())));
    }
    return fileDto;
  }

  public Boolean rename(String srcPath, String dstPath) throws Exception {
    if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(dstPath)) {
      throw new BusinessException("源文件名称或目的文件名称全路径不能为空");
    }

    logger.info("源文件名称全路径为：{}，目的文件全路径为：{}", srcPath, dstPath);
    return fileOperateCommonService.rename(srcPath, dstPath);
  }

  public CatalogDto getCatalogTreeByDatasourceId(String datasourceId, String parentCatalogPath)
      throws Exception {
    return null;
  }

  /**
   * 获取百分比
   *
   * @param num
   * @param totalPeople
   * @return
   */
  public String getPercent(Long num, Long totalPeople) {
    String percent;
    double p3;
    if (totalPeople == 0) {
      p3 = 0.0;
    } else {
      p3 = num * 1.0 / totalPeople;
    }
    NumberFormat nf = NumberFormat.getPercentInstance();
    // 控制保留小数点后几位，2：表示保留2位小数点
    nf.setMinimumFractionDigits(2);
    percent = nf.format(p3);
    return percent;
  }

  public List<String> getFilesByTemplate(String filePath, String templateId) {
    List<String> fileList = new ArrayList<>();
    CatalogTemplateDTO catalogTemplateDTO =
        CatalogTemplateDTO.builder().templateId(templateId).catalogPath(filePath).build();
    List<CatalogTemplateDTO> catalogTemplateDTOS =
        catalogTemplateService.selectList(catalogTemplateDTO);
    if (CollectionUtils.isNotEmpty(catalogTemplateDTOS)) {
      fileList =
          catalogTemplateDTOS.stream()
              .map(
                  catalogTemplateDTO1 ->
                      catalogTemplateDTO1
                          .getFilePath()
                          .replace(filePath + Constants.SINGLE_SLASH, ""))
              .collect(Collectors.toList());
    }
    return fileList;
  }

  public Boolean generateTemplate(CatalogTemplateDTO catalogTemplateDTO) {
    CheckParaUtils.checkStringValidity(catalogTemplateDTO.getCatalogPath(), logger, "上传文件路径不能为空！");
    CheckParaUtils.checkStringValidity(catalogTemplateDTO.getFilePath(), logger, "上传文件名称不能为空！");

    String filePath =
        catalogTemplateDTO.getCatalogPath() + File.separator + catalogTemplateDTO.getFilePath();
    InputStream inputFileStream = null;
    try {
      Path path = new Path(filePath);
      String fileName = path.getName();
      BdpFileStatus fileStatus = fileOperateCommonService.getFileStatus(filePath);

      if (fileStatus != null) {
        inputFileStream = fileOperateCommonService.open(filePath);

        // 根据文件自动生成模板（判断模板不存在，则新建模板）
        String templateId = templateService.saveTemplate(filePath, inputFileStream, fileName);

        // 自动将该文件和模板关联
        CatalogTemplateDTO catalogTemplate = new CatalogTemplateDTO();
        catalogTemplate.setCatalogPath(catalogTemplateDTO.getCatalogPath());
        catalogTemplate.setFilePath(catalogTemplateDTO.getFilePath());
        catalogTemplate.setTemplateId(templateId);
        saveUploadInfo(catalogTemplate);
      }
    } catch (Exception e) {
      logger.error("自动生成模板报错,原因是:" + e.getMessage());
      throw new BusinessException("自动生成模板报错,原因是:" + e.getMessage());
    } finally {
      if (inputFileStream != null) {
        try {
          inputFileStream.close();
        } catch (Exception e) {
          logger.error(e.getMessage(), e);
        }
      }
    }

    return true;
  }

  public void asyncDeleteFileData(String filePath) throws Exception {
    DelFileTask delFileTask = new DelFileTask(filePath);
    delFileThreadPool.execute(delFileTask);
  }

  public void deleteFileData(String filePath) throws Exception {
    jobFileService.deleteFileData(filePath);
  }

  public class DelFileTask implements Runnable {
    // 这里实现runnable接口
    private String filePath;

    public DelFileTask(String filePath) {
      this.filePath = filePath;
    }

    // 把获取的数据进行处理
    @Override
    public void run() {
      AsyncFileDTO asyncFileDTO = null;
      try {
        AsyncFileDTO asyncFileDTOQuery = new AsyncFileDTO();
        asyncFileDTOQuery.setFilePath(filePath);
        asyncFileDTO = asyncFileService.selectOne(asyncFileDTOQuery);
        int i = 0;
        while (asyncFileDTO == null && i < 10) {
          Thread.sleep(1000);
          asyncFileDTO = asyncFileService.selectOne(asyncFileDTOQuery);
          i++;
          logger.info("尝试第" + i + "次获取文件{}的数据", filePath);
        }
        if (asyncFileDTO == null) {
          logger.info("文件是:{}的数据不存在", filePath);
        }

        if (asyncFileDTO != null) {
          asyncFileDTO.setStatus(FileStatusEnum.DELETING.getCode());
          asyncFileDTO.setTotalRecords(jobFileService.countDeviceData(filePath));
          asyncFileService.updateByPrimaryKey(asyncFileDTO);
        }

        deleteFileData(filePath);
        logger.info("异步删除文件数据成功,文件是:{}", filePath);

        if (asyncFileDTO != null) {
          asyncFileService.deleteByPrimaryKey(asyncFileDTO.getId());
          logger.info("删除bdp_dcs_async_file成功,文件是:{}", filePath);
        }
      } catch (Exception e) {
        e.printStackTrace();
        if (asyncFileDTO != null) {
          asyncFileDTO.setStatus(FileStatusEnum.DELETE_FAIL.getCode());
          asyncFileService.updateByPrimaryKey(asyncFileDTO);
        }
        logger.error("异步删除文件数据出错,文件是:{},原因是:{}", filePath, e.getMessage());
      }
    }
  }

  public Boolean deleteCacheData(String hdfsPath, String fileName, String fileMd5)
      throws Exception {
    if (StringUtils.isEmpty(hdfsPath)) {
      logger.error("删除缓存数据失败,hdfsPath={}", hdfsPath);
      throw new BusinessException("没有传入待删除的文件路径");
    }

    // 删除redis中缓存分片信息，进度信息
    fileChunkUtils.deleteChunksInfoInCache(
        fileMd5, hdfsPath, hdfsPath + File.separator + fileName, fileName);
    return true;
  }

  public Boolean deleteCacheDataByKey(String key) throws Exception {
    logger.info("删除缓存数据,key={}", key);
    if (StringUtils.isEmpty(key)) {
      throw new BusinessException("没有传入待删除的key");
    }

    redisCacheHelper.del(key);
    return true;
  }
}
